/*
 * RString.h
 *
 *  Created on: 29.08.2013.
 *      Author: Aco
 */

#ifndef RSTRING_H_
#define RSTRING_H_

#include <cwchar>
#include <vector>
#include <cstdarg>
#include <string>
#include "integers.h"

class RString
{
private:

	struct RSNode
	{
		uint16_t * dataPtr;
		int refCount;
		int cSize;

		RSNode() { dataPtr = NULL; refCount = 0; cSize = 0; }
	};

	static const char NULL_CHAR;
	static std::vector<RSNode> nodeStore;
	static int nodeMin;
	static int nodeMax;

	static int s_getNewNode();
	static void s_releaseNode(int id);
	static void s_lockNode(int id);

	static int s_compare(const uint16_t * a, const char * b);
	static int s_compare(const uint16_t * a, const uint16_t * b);
	static int s_compare(const uint16_t * a, const uint32_t * b);

	static void s_convert(const char * src, uint16_t * dst, int max);
	static void s_convert(const uint32_t * src, uint16_t * dst, int max);

	void prepStorage(int l, bool retain);
	void prepForMod();
	void copyBack();

	void assign(const RString & src);

	void assignChars(const char * src, int origin);
	void assignChars(const uint16_t * src, int origin);
	void assignChars(const uint32_t * src, int origin);

	void shiftChars(int pos, int dir);

	void defInit();

	void checkLength();

	uint16_t * data;
	int chunkLength;
	int storeID;
	bool shared;
	uint32_t length;

	char * cdata;
	int cdLength;
	bool cdDirty;

public:
	RString();
	RString(const std::string & src);
	RString(const RString & src);
	RString(const char * cstr, ...);
	RString(const uint16_t * wstr);
	RString(const uint32_t * wstr);

	~RString();

	uint32_t getLength() const;
	const uint16_t * getWData() const;
	const char * c_str() const;

	void swapEndianness();

	void clear();
	void setF(const char * fmt, ...);
	void appendF(const char * fmt, ...);

	bool toInt(int & out) const;
	bool toFloat(float & out) const;

	bool startsWith(const char * prefix) const;
	bool endsWith(const char * suffix) const;

	void setCharAt(uint16_t c, int pos);
	void insertCharAt(uint16_t c, int pos);
	void insertStringAt(const RString & src, int pos);
	void deleteRange(int start, int end);

	int compareTo(const RString & src) const;
	int countChars(uint16_t c) const;

	char charAt(int i) const;
	uint16_t utfCharAt(int i) const;

	RString substring(int start, int end) const;

	bool isEmpty() const;
	bool notEmpty() const;

	RString & operator= (const RString &src);
	RString & operator= (const char * src);
	RString & operator= (const uint16_t * src);
	RString & operator= (const uint32_t * src);

	RString & operator+= (const RString &src);
	RString & operator+= (const char * src);
	RString & operator+= (const uint16_t * src);
	RString & operator+= (const uint32_t * src);

	RString & operator+= (uint16_t c);

	bool operator== (const RString &src) const;
	bool operator== (const char * src) const;
	bool operator== (const uint16_t * src) const;
	bool operator== (const uint32_t * src) const;

	RString operator+ (const RString &src) const;
	RString operator+ (const char * src) const;

	static void dumpStats();
};


#endif /* RSTRING_H_ */
